package com.token.aspect;

import cn.hutool.aop.aspects.SimpleAspect;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.token.annotation.TransField;
import com.token.service.DictDataService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;


/**
 * @auther: henriy
 * @Date: 2024/6/17
 */
@Aspect
@Component
public class TransAspect extends SimpleAspect {

    private static final long serialVersionUID = -4034897445169933339L;

    @Resource
    private DictDataService dictDataService;

    @Pointcut("execution(* *..*Service.*(..))")
    public void aroundPointcut() {
    }

    @Around("aroundPointcut()")
    public Object aroundService(ProceedingJoinPoint pjp) throws Throwable {
        return transResult(pjp.proceed());
    }

    /**
     * 判断
     *
     * @param result
     * @return
     */
    private Object transResult(Object result) {
        if (ObjectUtil.isNull(result)) {
            return result;
        }

        // 返回的结果类型是否为基本类型
        if (result.getClass().isPrimitive()) {
            return result;
        }

        // 返回的结果类型是否为String类型
        if (result instanceof String) {
            return result;
        }

        // 返回的结果类型是否为分页类型，IPage根据项目中的实际分页去调整
        if (result instanceof IPage) {
            if (CollUtil.isNotEmpty(((IPage<?>) result).getRecords())) {
                ((IPage<?>) result).getRecords().forEach(this::translate);
            }

            return result;
        }

        // 返回的结果类型是否为集合类型
        if (result instanceof Collection) {
            if (CollUtil.isNotEmpty(((List<?>) result))) {
                ((List<?>) result).forEach(this::translate);
            }

            return result;
        }

        translate(result);
        return result;
    }

    /**
     * 翻译
     *
     * @param result
     */
    public void translate(Object result) {
        Class<Field> clazz = (Class<Field>) result.getClass();
        List<Field> fields = new ArrayList<>();
        while (clazz != null) {
            fields.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
            clazz = (Class<Field>) clazz.getSuperclass();
        }

        for (Field field : fields) {
            // 判断属性之上是否有自己定义的注解
            TransField annotation = field.getAnnotation(TransField.class);
            if (ObjectUtil.isNotEmpty(annotation)) {
                String type = annotation.type();
                // 处理嵌套在目标对象类中的集合类型翻译
                final Object fieldValue = BeanUtil.getFieldValue(result, field.getName());
                final boolean isCollection = fieldValue instanceof Collection;
                if (isCollection) {
                    Collection<?> list = (Collection<?>) fieldValue;
                    if (CollectionUtils.isEmpty(list)) continue;
                    for (Object row : list) {
                        if (row.getClass().isPrimitive()) continue;
                        this.translate(row);
                    }
                }

                convertObject(annotation, field, result, type);
            }
        }
    }

    /**
     * 转化
     *
     * @param annotation 注解
     * @param field      字段
     * @param result     结果
     * @param type       字典类型值
     */
    private void convertObject(TransField annotation, Field field, Object result, String type) {
        try {
            field.setAccessible(true);
            PropertyDescriptor pd = new PropertyDescriptor(annotation.target(), result.getClass());
            Method writeName = pd.getWriteMethod();
            writeName.invoke(result, getTargetValue(field, result, type));
        } catch (InvocationTargetException | IllegalAccessException | IntrospectionException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取目标对象属性
     *
     * @param field
     * @param obj
     * @param type
     * @return
     */
    private String getTargetValue(Field field, Object obj, String type) {
        // 如果有，则进行转换
        Object filedValue = BeanUtil.getFieldValue(obj, field.getName());
        if (ObjectUtil.isNotEmpty(filedValue)) {
            return dictDataService.getDictValueByCode(type, String.valueOf(filedValue));
        }

        return "";
    }

}

